#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

// #include <cstring>
// #include <fstream>
// #include <iostream>
// #include <sstream>

// #include <stddef.h>

#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/opensslv.h>

#define PROXY_PORT 8888
// #define DEST_HOST "admin.hdedu.fun"
#define DEST_HOST "192.168.1.1"
#define DEST_PORT 443

void handle_error(const char *msg) {
    perror(msg);
    exit(EXIT_FAILURE);
}

void handle_openssl_error() {
    unsigned long error;
    while ((error = ERR_get_error()) != 0) {
        fprintf(stderr, "OpenSSL Error: %s\n", ERR_error_string(error, NULL));
    }
}

void handle_ssl_error(SSL *ssl, int result) {
    int ssl_error = SSL_get_error(ssl, result);

    if (ssl_error == SSL_ERROR_SYSCALL) {
        // 系统调用错误
        perror("SSL_accept failed");
    } else {
        // OpenSSL 错误栈追踪
        unsigned long err;
        while ((err = ERR_get_error()) != 0) {
            fprintf(stderr, "OpenSSL Error: %s\n", ERR_error_string(err, NULL));
        }
    }
}

void info_callback(const SSL *ssl, int type, int val) {
    printf("SSL info_callback info: type=%d, val=%d\n", type, val);
    if (type & SSL_CB_HANDSHAKE_START) {
        printf("SSL handshake started.\n");
        // Your custom handshake logic here...
    }
    if (type & SSL_CB_HANDSHAKE_DONE) {
        printf("SSL handshake done.\n");
        // Your custom handshake completion logic here...
    }

    if (type & SSL_CB_ALERT) {
        uint32_t max_fragment_size = SSL_get_recv_max_early_data(ssl);
        printf("SSL alert max_fragment_size == %d \n", max_fragment_size);

        fprintf(stderr, "SSL alert: %s:%s\n", SSL_alert_type_string_long(val), SSL_alert_desc_string_long(val));
    }

    if (val > 1){
        int state = SSL_accept((SSL *)ssl);
        printf("SSL handshake State == %d.\n", state);
    }
}


void init_openssl() {

    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();


    // SSL_load_error_strings();
    // OpenSSL_add_ssl_algorithms();
}

SSL_CTX *create_context() {
    const SSL_METHOD *method;
    SSL_CTX *ctx;

    method = SSLv23_client_method(); // You might want to use SSLv23_server_method() for modern versions
    // method = TLS_client_method(); // You might want to use TLS_client_method() for modern versions
    // method = TLS_server_method();
    // method = TLSv1_server_method();

    // SSL_set_options(3)

    if ((ctx = SSL_CTX_new(method)) == NULL) {
        handle_error("Error creating SSL context");
        ERR_print_errors_fp(stderr);
        printf("create_context failed 111 \n");
    }

    // print_supported_versions(method);

    // 设置证书文件的口令
    // SSL_CTX_set_default_passwd_cb_userdata(ctx, "wendy");

    printf("create_context success 222 \n");

    SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

    // SSL_CTX_set_max_send_fragment(ctx, 16384 * 10);

    return ctx;
}

SSL_CTX* load_ctx(){
    // printf("Supported SSL/TLS Methods: %s\n", OpenSSL_version(OPENSSL_METHOD));

    // 初始化 OpenSSL 库
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();

    printf("OpenSSL Version: %s\n", OpenSSL_version(OPENSSL_VERSION));

    
    SSL_CTX* ctx = create_context();
    
    SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);

    // 创建 SSL 上下文
    // ssl_ctx = SSL_CTX_new(TLS_server_method());
    // if (!ssl_ctx) {
    //     perror("Error creating SSL context");
    //     close(client_socket);
    //     exit(EXIT_FAILURE);
    // }

    // 设置服务器端证书和私钥
    printf("Start certificate 111:: \n");
    if (SSL_CTX_use_certificate_file(ctx, "./cert/hdedu.crt", SSL_FILETYPE_PEM) <= 0 ) {
        printf("setting certificate ERROR 111:: \n");
        perror("Error setting certificate or private key ::: \n");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    if (SSL_CTX_use_PrivateKey_file(ctx, "./cert/hdedu.key", SSL_FILETYPE_PEM) <= 0) {
        printf("setting certificate ERROR 222:: \n");
        perror("Error setting certificate or private key ::: \n");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    // 设置密码套件
    // if (SSL_CTX_set_cipher_list(ctx, "TLS_AES_256_GCM_SHA384") != 1) {
    //     fprintf(stderr, "Failed to set cipher list.\n");
    //     ERR_print_errors_fp(stderr);
    //     exit(EXIT_FAILURE); // 处理错误，可能需要中止程序或采取其他措施
    // }

    // SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
    // SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);


    return ctx;
}

// 初始化 SSL CTX 
int init_ssl(int client_socket, SSL_CTX* ctx){

    // 初始化 OpenSSL 库
    // SSL_library_init();
    // OpenSSL_add_all_algorithms();
    // SSL_load_error_strings();

    printf("\n init_ssl 111.... client_socket = %d \n ", client_socket);

    // SSL_CTX* ctx = load_ctx();

    printf("init ssl 000 \n");
    SSL *ssl = SSL_new(ctx);
    SSL_set_fd(ssl, client_socket);
    printf("init ssl 111 :: %d \n", SSL_in_init(ssl));
    printf("init ssl 111 222:: %d \n", SSL_is_init_finished(ssl));

    SSL_set_info_callback(ssl, info_callback); // 设置握手回调输出信息 
    // printf("init_ssl SSL_set_info_callback result: %d\n", call_int);
    printf("init_ssl Supported Cipher List: %s\n", SSL_get_cipher_list(ssl, 0));

    // 获取SSL/TLS协议版本
    const char *protocol_version = SSL_get_version(ssl);
    printf("Negotiated protocol version: %s\n", protocol_version);

    // SSL_CTX_set_max_send_fragment(ctx, 16384 * 10);

    // 
    // SSL_set_recv_max_early_data(ssl, 16384 * 10);
    SSL_CTX_set_max_pipelines(ctx, 10);
    SSL_CTX_set_max_send_fragment(ctx, 4096);


    long ssl_result = SSL_get_verify_result(ssl);
    if (ssl_result == X509_V_OK) {
        printf("Certificate verification passed.\n");
    } else {
        printf("Certificate verification failed: %s\n", X509_verify_cert_error_string(ssl_result));
    }
    // printf("Negotiated SSL_get_verify_result: %ld \n", ssl_result);

    // 获取支持的加密套件列表
    // STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl);

    // // 遍历加密套件列表
    // for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
    //     const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
    //     printf("Cipher: %s\n", SSL_CIPHER_get_name(cipher));
    // }


    int state;
    // printf("Start SSL_stateless 111::  %d\n", state);
    while ( (state = SSL_connect(ssl)) <= 0 ) {
        printf("Start SSL_stateless 111::  %d\n", state);

        // handle_ssl_error(ssl, state);
        // if ( state == 0 ){
        //     continue;
        // }

        int ssl_error = SSL_get_error(ssl, state);
        printf("SSL_accept ERROR 000:: ssl_error==%d \n", ssl_error);
        if (ssl_error == SSL_ERROR_WANT_READ || ssl_error == SSL_ERROR_WANT_WRITE) {
            // 等待更多数据或写入更多数据，继续循环
            continue;
        }

        printf("SSL_accept ERROR 111:: state==%d \n", state);
        // ERR_print_errors_fp(stderr);
        // handle_openssl_error();

        int err = SSL_get_error(ssl, state);
        fprintf(stderr, "SSL_accept error 222: %d\n", err);
        switch (err) {
            case SSL_ERROR_WANT_READ:
                // The operation did not complete; wait for a readable socket
                // and try again later.
                // This is not an error condition.
                break;
            case SSL_ERROR_WANT_WRITE:
                // The operation did not complete; wait for a writable socket
                // and try again later.
                // This is not an error condition.
                break;
            case SSL_ERROR_SYSCALL:
                // A low-level I/O error occurred. Check the underlying socket
                // for more information.
                perror("SSL_accept syscall error");
                break;
            case SSL_ERROR_SSL:
                // A failure in the SSL library.
                ERR_print_errors_fp(stderr);
                break;
            // Add more cases as needed
            default:
                // Handle other cases
                break;
        }


        SSL_shutdown(ssl);
        SSL_free(ssl);
        SSL_CTX_free(ctx);
        close(client_socket);
        exit(EXIT_FAILURE);
    } 


    printf("Start SSL_write 111:: \n");
    char buffer[1024];
    int bytes_received;

    // 读取解密后的数据
    bytes_received = SSL_read(ssl, buffer, sizeof(buffer));

    printf("Start SSL_write 222:: buffer = %s\n", buffer);
    // const char* response = "Hello, SSL World!\n";
    // SSL_write(ssl, response, strlen(response));

    // 关闭 SSL 连接
    SSL_shutdown(ssl);
    SSL_free(ssl);
    // SSL_CTX_free(ctx);
    close(client_socket);
    return 0;
}

void handle_client(SSL* ssl) {
    // 在这里处理客户端连接
    // 在实际应用中，你可能需要在这里进行数据交换、业务逻辑等操作
    // 例如，你可以使用 SSL_read 和 SSL_write 函数进行数据传输

    const char* response = "Hello, SSL World!\n";
    SSL_write(ssl, response, strlen(response));

    // 关闭 SSL 连接
    SSL_shutdown(ssl);
    SSL_free(ssl);
}


void handle_https_connection(SSL *ssl) {
    char buffer[1024];
    int bytes_received;

    // 读取解密后的数据
    bytes_received = SSL_read(ssl, buffer, sizeof(buffer));

    if (bytes_received > 0) {
        // 在这里处理接收到的数据，可能包括 HTTP 头部解析等
        // 请注意，这里的数据是解密后的数据
        printf("Received data: %.*s\n", bytes_received, buffer);
    } else if (bytes_received == 0) {
        printf("Connection closed by the remote host.\n");
    } else {
        perror("Error receiving data");
    }
}



